
%{
#include "sql_tree.h"
#include "sql_y.h"

#undef YY_INPUT
#define YY_INPUT(buffer, result, max_size) ( result = parser_yyinput(buffer, max_size))

#define YY_NEVER_INTERACTIVE 1

static void     begin_token      (const char* s);
static void     begin_token_name (const char* s);

static char*    read_string(char zy, char end);
static char*    read_c_style_comment   (char* s, int size);
static char*    read_cpp_style_comment (char* s, int size);
static char*    read_sql_style_comment (char* s, int size);

static int      parser_yyinput(char* buffer, int max_size);

%}

%%

[ \t]+                                    { }
\r\n                                      { SQL_this_parser->line++; SQL_this_parser->column = 0; }
\r                                        { }
\n                                        { SQL_this_parser->line++; SQL_this_parser->column = 0; }

[aA][cC][tT][iI][oO][nN]                        { begin_token(yytext);   return SQL_ACTION; }
[aA][dD][dD]                                    { begin_token(yytext);   return SQL_ADD; }
[aA][lL][lL]                                    { begin_token(yytext);   return SQL_ALL; }
[aA][lL][tT][eE][rR]                            { begin_token(yytext);   return SQL_ALTER; }
[aA][nN][dD]                                    { begin_token(yytext);   return SQL_AND; }
[aA][nN][yY]                                    { begin_token(yytext);   return SQL_ANY; }
[aA][sS]                                        { begin_token(yytext);   return SQL_AS; }
[aA][sS][cC]                                    { begin_token(yytext);   return SQL_ASC; }
[aA][tT]                                        { begin_token(yytext);   return SQL_AT; }
[aA][vV][gG]                                    { begin_token(yytext);   return SQL_AVG; }
[aA][tT][tT][rR][iI][bB][uU][tT][eE]            { begin_token(yytext);   return SQL_ATTRIBUTE; }

[bB][eE][tT][wW][eE][eE][nN]                    { begin_token(yytext);   return SQL_BETWEEN; }
[bB][iI][tT]                                    { begin_token(yytext);   return SQL_BIT; }
[bB][iI][tT]_[lL][eE][nN][gG][tT][hH]           { begin_token(yytext);   return SQL_BIT_LENGTH; }
[bB][oO][tT][hH]                                { begin_token(yytext);   return SQL_BOTH; }
[bB][yY]                                        { begin_token(yytext);   return SQL_BY; }

[cC][aA][sS][cC][aA][dD][eE]                    { begin_token(yytext);   return SQL_CASCADE; }
[cC][aA][sS][cC][aA][dD][eE][dD]                { begin_token(yytext);   return SQL_CASCADED; }
[cC][aA][sS][eE]                                { begin_token(yytext);   return SQL_CASE; }
[cC][aA][sS][tT]                                { begin_token(yytext);   return SQL_CAST; }
[cC][hH][aA][rR][aA][cC][tT][eE][rR]            { begin_token(yytext);   return SQL_CHAR; }
[cC][hH][aA][rR]                                { begin_token(yytext);   return SQL_CHAR; }
[cC][hH][aA][rR][aA][cC][tT][eE][rR]_[lL][eE][nN][gG][tT][hH]        { begin_token(yytext);   return SQL_CHARACTER_LENGTH; }
[cC][hH][aA][rR]_[lL][eE][nN][gG][tT][hH]       { begin_token(yytext);   return SQL_CHARACTER_LENGTH; }
[cC][hH][eE][cC][kK]                            { begin_token(yytext);   return SQL_CHECK; }
[cC][oO][aA][lL][eE][sS][cC][eE]                { begin_token(yytext);   return SQL_COALESCE; }
[cC][oO][lL][uU][mM][nN]                        { begin_token(yytext);   return SQL_COLUMN; }
[cC][oO][mM][mM][iI][tT]                        { begin_token(yytext);   return SQL_COMMIT; }
[cC][oO][nN][nN][eE][cC][tT]                    { begin_token(yytext);   return SQL_CONNECT; }
[cC][oO][nN][sS][tT][rR][aA][iI][nN][tT]        { begin_token(yytext);   return SQL_CONSTRAINT; }
[cC][oO][uU][nN][tT]                            { begin_token(yytext);   return SQL_COUNT; }
[cC][rR][eE][aA][tT][eE]                        { begin_token(yytext);   return SQL_CREATE; }
[cC][rR][oO][sS][sS]                            { begin_token(yytext);   return SQL_CROSS; }
[cC][uU][rR][rR][eE][nN][tT]                    { begin_token(yytext);   return SQL_CURRENT; }
[cC][uU][rR][rR][eE][nN][tT]_[dD][aA][tT][eE]   { begin_token(yytext);   return SQL_CURRENT_DATE; }
[cC][uU][rR][rR][eE][nN][tT]_[tT][iI][mM][eE]   { begin_token(yytext);   return SQL_CURRENT_TIME; }
[cC][uU][rR][rR][eE][nN][tT]_[tT][iI][mM][eE][sS][tT][aA][mM][pP]     { begin_token(yytext);   return SQL_CURRENT_TIMESTAMP; }
[cC][uU][rR][rR][eE][nN][tT]_[uU][sS][eE][rR]   { begin_token(yytext);   return SQL_CURRENT_USER; }

[dD][aA][tT][eE]                                { begin_token(yytext);   return SQL_DATE; }
[dD][aA][tT][eE][tT][iI][mM][eE]                { begin_token(yytext);   return SQL_DATETIME; }
[dD][eE][cC]                                    { begin_token(yytext);   return SQL_NUMERIC; }
[dD][eE][cC][iI][mM][aA][lL]                    { begin_token(yytext);   return SQL_NUMERIC; }
[dD][eE][fF][aA][uU][lL][tT]                    { begin_token(yytext);   return SQL_DEFAULT; }
[dD][eE][fF][eE][rR][rR][aA][bB][lL][eE]        { begin_token(yytext);   return SQL_DEFERRABLE; }
[dD][iI][fF][fF][eE][rR][eE][nN][cC][eE]        { begin_token(yytext);   return SQL_DIFFERENCE; }
[dD][eE][fF][eE][rR][rR][eE][dD]                { begin_token(yytext);   return SQL_DEFERRED; }
[dD][eE][lL][eE][tT][eE]                        { begin_token(yytext);   return SQL_DELETE; }
[dD][eE][sS][cC]                                { begin_token(yytext);   return SQL_DESC; }
[dD][iI][sS][tT][iI][nN][cC][tT]                { begin_token(yytext);   return SQL_DISTINCT; }
[dD][oO][uU][bB][lL][eE]                        { begin_token(yytext);   return SQL_DOUBLE; }
[dD][rR][oO][pP]                                { begin_token(yytext);   return SQL_DROP; }

[eE][lL][sS][eE]                                { begin_token(yytext);   return SQL_ELSE; }
[eE][nN][dD]                                    { begin_token(yytext);   return SQL_END; }
[eE][sS][cC][aA][pP][eE]                        { begin_token(yytext);   return SQL_ESCAPE; }
[eE][xX][cC][eE][pP][tT]                        { begin_token(yytext);   return SQL_EXCEPT; }
[eE][xX][eE][cC][uU][tT][eE]                    { begin_token(yytext);   return SQL_EXECUTE; }
[eE][xX][iI][sS][tT][sS]                        { begin_token(yytext);   return SQL_EXISTS; }
[eE][xX][tT][rR][aA][cC][tT]                    { begin_token(yytext);   return SQL_EXTRACT; }
[eE][vV][aA][lL][uU][aA][tT][eE]                { begin_token(yytext);   return SQL_EVALUATE; }

[fF][aA][lL][sS][eE]                            { begin_token(yytext);   return SQL_FALSE; }
[fF][lL][oO][aA][tT]                            { begin_token(yytext);   return SQL_FLOAT; }
[fF][oO][rR]                                    { begin_token(yytext);   return SQL_FOR; }
[fF][oO][rR][eE][iI][gG][nN]                    { begin_token(yytext);   return SQL_FOREIGN; }
[fF][rR][oO][mM]                                { begin_token(yytext);   return SQL_FROM; }

[gG][rR][aA][nN][tT]                            { begin_token(yytext);   return SQL_GRANT; }
[gG][rR][oO][uU][pP]                            { begin_token(yytext);   return SQL_GROUP; }

[hH][aA][vV][iI][nN][gG]                        { begin_token(yytext);   return SQL_HAVING; }

[iI][mM][mM][eE][dD][iI][aA][tT][eE]            { begin_token(yytext);   return SQL_IMMEDIATE; }
[iI][nN]                                        { begin_token(yytext);   return SQL_IN; }
[iI][nN][iI][tT][iI][aA][lL][lL][yY]            { begin_token(yytext);   return SQL_INITIALLY; }
[iI][nN][nN][eE][rR]                            { begin_token(yytext);   return SQL_INNER; }
[iI][nN][sS][eE][rR][tT]                        { begin_token(yytext);   return SQL_INSERT; }
[iI][nN][tT]                                    { begin_token(yytext);   return SQL_INTEGER; }
[iI][nN][tT][eE][gG][eE][rR]                    { begin_token(yytext);   return SQL_INTEGER; }
[iI][nN][tT][eE][rR][sS][eE][cC][tT]            { begin_token(yytext);   return SQL_INTERSECT; }
[iI][nN][tT][oO]                                { begin_token(yytext);   return SQL_INTO; }
[iI][sS]                                        { begin_token(yytext);   return SQL_IS; }

[jJ][oO][iI][nN]                                { begin_token(yytext);   return SQL_JOIN; }
[kK][eE][yY]                                    { begin_token(yytext);   return SQL_KEY; }

[lL][eE][aA][dD][iI][nN][gG]                    { begin_token(yytext);   return SQL_LEADING; }
[lL][eE][fF][tT]                                { begin_token(yytext);   return SQL_LEFT; }
[lL][eE][vV][eE][lL]                            { begin_token(yytext);   return SQL_LEVEL; }
[lL][iI][kK][eE]                                { begin_token(yytext);   return SQL_LIKE; }
[lL][oO][cC][aA][lL]                            { begin_token(yytext);   return SQL_LOCAL; }
[lL][oO][wW][eE][rR]                            { begin_token(yytext);   return SQL_LOWER; }

[mM][aA][xX]                                    { begin_token(yytext);   return SQL_MAX; }
[mM][iI][nN]                                    { begin_token(yytext);   return SQL_MIN; }
[mM][eE][mM][bB][eE][rR][sS]                    { begin_token_name(yytext); return SQL_MEMBERS; }

[nN][aA][tT][iI][oO][nN][aA][lL]                { begin_token(yytext);   return SQL_NATIONAL; }
[nN][aA][tT][uU][rR][aA][lL]                    { begin_token(yytext);   return SQL_NATURAL; }
[nN][cC][hH][aA][rR]                            { begin_token(yytext);   return SQL_NCHAR; }
[nN][oO]                                        { begin_token(yytext);   return SQL_NO; }
[nN][oO][nN][eE]                                { begin_token(yytext);   return SQL_NONE; }
[nN][oO][tT]                                    { begin_token(yytext);   return SQL_NOT; }
[nN][uU][lL][lL]                                { begin_token(yytext);   return SQL_NULL; }
[nN][uU][lL][lL][iI][fF]                        { begin_token(yytext);   return SQL_NULLIF; }
[nN][uU][mM][eE][rR][iI][cC]                    { begin_token(yytext);   return SQL_NUMERIC; }

[oO][cC][tT][eE][tT]_[lL][eE][nN][gG][tT][hH]   { begin_token(yytext);   return SQL_OCTET_LENGTH; }
[oO][fF]                                        { begin_token(yytext);   return SQL_OF; }
[oO][nN]                                        { begin_token(yytext);   return SQL_ON; }
[oO][nN][lL][yY]                                { begin_token(yytext);   return SQL_ONLY; }
[oO][pP][tT][iI][oO][nN]                        { begin_token(yytext);   return SQL_OPTION; }
[oO][rR]                                        { begin_token(yytext);   return SQL_OR; }
[oO][rR][dD][eE][rR]                            { begin_token(yytext);   return SQL_ORDER; }
[oO][uU][tT][eE][rR]                            { begin_token(yytext);   return SQL_OUTER; }

[pP][oO][sS][iI][tT][iI][oO][nN]                { begin_token(yytext);   return SQL_POSITION; }
[pP][rR][eE][cC][iI][sS][iI][oO][nN]            { begin_token(yytext);   return SQL_PRECISION; }
[pP][rR][iI][mM][aA][rR][yY]                    { begin_token(yytext);   return SQL_PRIMARY; }
[pP][rR][iI][oO][rR]                            { begin_token(yytext);   return SQL_PRIOR; }
[pP][rR][iI][vV][iI][lL][eE][gG][eE][sS]        { begin_token(yytext);   return SQL_PRIVILEGES; }
[pP][aA][sS][sS][wW][oO][rR][dD]                { begin_token_name(yytext);   return SQL_PASSWORD; }

[rR][eE][aA][lL]                                { begin_token(yytext);   return SQL_FLOAT; }
[rR][eE][fF][eE][rR][eE][nN][cC][eE][sS]        { begin_token(yytext);   return SQL_REFERENCES; }
[rR][eE][sS][tT][rR][iI][cC][tT]                { begin_token(yytext);   return SQL_RESTRICT; }
[rR][eE][vV][oO][kK][eE]                        { begin_token(yytext);   return SQL_REVOKE; }
[rR][iI][gG][hH][tT]                            { begin_token(yytext);   return SQL_RIGHT; }
[rR][oO][lL][lL][bB][aA][cC][kK]                { begin_token(yytext);   return SQL_ROLLBACK; }
[rR][eE][nN][aA][mM][eE]                        { begin_token(yytext);   return SQL_RENAME; }

[sS][eE][lL][eE][cC][tT]                        { begin_token(yytext);   return SQL_SELECT; }
[sS][eE][tT]                                    { begin_token(yytext);   return SQL_SET; }
[sS][mM][aA][lL][lL][iI][nN][tT]                { begin_token(yytext);   return SQL_SMALLINT; }
[sS][oO][mM][eE]                                { begin_token(yytext);   return SQL_SOME; }
[sS][uU][bB][sS][tT][rR][iI][nN][gG]            { begin_token(yytext);   return SQL_SUBSTRING; }
[sS][uU][mM]                                    { begin_token(yytext);   return SQL_SUM; }
[sS][tT][dD][dD][eE][vV]                        { begin_token_name(yytext); return SQL_STDDEV; }

[tT][aA][bB][lL][eE]                            { begin_token(yytext);   return SQL_TABLE; }
[tT][hH][eE][nN]                                { begin_token(yytext);   return SQL_THEN; }
[tT][iI][mM][eE]                                { begin_token(yytext);   return SQL_TIME; }
[tT][iI][mM][eE][sS][tT][aA][mM][pP]            { begin_token(yytext);   return SQL_TIMESTAMP; }
[tT][oO]                                        { begin_token(yytext);   return SQL_TO; }
[tT][rR][aA][iI][lL][iI][nN][gG]                { begin_token(yytext);   return SQL_TRAILING; }
[tT][rR][aA][nN][sS][lL][aA][tT][eE]            { begin_token(yytext);   return SQL_TRANSLATE; }
[tT][rR][iI][mM]                                { begin_token(yytext);   return SQL_TRIM; }
[tT][rR][uU][eE]                                { begin_token(yytext);   return SQL_TRUE; }

[uU][nN][iI][oO][nN]                            { begin_token(yytext);   return SQL_UNION; }
[uU][nN][iI][qQ][uU][eE]                        { begin_token(yytext);   return SQL_UNIQUE; }
[uU][pP][dD][aA][tT][eE]                        { begin_token(yytext);   return SQL_UPDATE; }
[uU][pP][pP][eE][rR]                            { begin_token(yytext);   return SQL_UPPER; }
[uU][sS][eE][rR]                                { begin_token(yytext);   return SQL_USER; }
[uU][sS][iI][nN][gG]                            { begin_token(yytext);   return SQL_USING; }

[vV][aA][lL][uU][eE][sS]                        { begin_token(yytext);   return SQL_VALUES; }
[vV][aA][rR][cC][hH][aA][rR]                    { begin_token(yytext);   return SQL_VARCHAR; }
[vV][aA][rR][yY][iI][nN][gG]                    { begin_token(yytext);   return SQL_VARYING; }
[vV][iI][eE][wW]                                { begin_token(yytext);   return SQL_VIEW; }

[wW][hH][eE][nN]                                { begin_token(yytext);   return SQL_WHEN; }
[wW][hH][eE][rR][eE]                            { begin_token(yytext);   return SQL_WHERE; }
[wW][iI][tT][hH]                                { begin_token(yytext);   return SQL_WITH; }
[wW][oO][rR][kK]                                { begin_token(yytext);   return SQL_WORK; }

"->"                                            { begin_token(yytext);   return SQL_RIGHT_ARROW; }
"||"                                            { begin_token(yytext);   return SQL_STRCAT; }

"<>"                                            { begin_token(yytext);   return SQL_COMP_NOT_EQ; }
">="                                            { begin_token(yytext);   return SQL_COMP_GE; }
"<="                                            { begin_token(yytext);   return SQL_COMP_LE; }
"!="                                            { begin_token(yytext);   return SQL_NOT_EQUAL_SIGN; };
"=="                                            { begin_token(yytext);   return SQL_EQUAL_SIGN; };
['?'][':'][0-9]+                                { begin_token(yytext);   
                                                  yylval.number = sql_read_unsigned_dec ( yytext + 2);
                                                  return SQL_PARAM_HEADER; }

[0-9]+                                          { begin_token(yytext); 
                                                  yylval.number = sql_read_unsigned_dec ( yytext );
                                                  return SQL_UNSIGNED_INTEGER; 
                                                }

([0-9]+[Ee][\+\-]?[0-9]+[fF]?)|([0-9]*\.[0-9]+([Ee][\+\-]?[0-9]+)?[fF]?)|([0-9]+\.[0-9]*([Ee][\+\-]?[0-9]+)?[fF]?)     {
                        begin_token (yytext);
                        yylval.real_num = atof (yytext);
                        return SQL_UNSIGNED_REAL;
                      }

([a-zA-Z_%#])|([a-zA-Z_%#0-9])* { 
                        begin_token_name(yytext);
                        return SQL_ID_NAME;
                      }

[nN]\'                {
                        yylval.cptr = read_string('\\','\'');
                        return SQL_NCHAR_STRING;
                      }

[bB]\'                {
                        yylval.cptr = read_string('\\','\'');
                        return SQL_BIT_STRING;
                      }

[xX]\'                {
                        yylval.cptr = read_string('\\','\'');
                        return SQL_HEX_STRING; 
                      }

\'                    {
                        yylval.cptr = read_string('\\','\'');
                        return SQL_CHAR_STRING;
                      }

\"                    {
                        yylval.cptr = read_string('\\','\"');
                        return SQL_CHAR_STRING;
                      }


"["                   {
                        yylval.cptr = read_string (0, ']');
                        return SQL_BracketDelimitedIdName; 
                      }


"//"                  { 
                        char hints[256];
                        yylval.number = sql_read_hint( read_cpp_style_comment(hints, sizeof(hints) ) );
                         
                        if (yylval.number) 
                        {
                          return SQL_HINT;
                        }
                      }


"/*"                  {
                        char hints[256];
                        yylval.number = sql_read_hint ( read_c_style_comment( hints, sizeof(hints) ) ); 
                        if (yylval.number) 
                        {
                          return SQL_HINT;
                        }
                      }

"--"                  {
                        char hints[256];
                        yylval.number = sql_read_hint ( read_sql_style_comment ( hints, sizeof(hints) ) );
                         
                        if (yylval.number) 
                        {
                          return SQL_HINT;
                        }
                      }

\$                    { begin_token(yytext);   return SQL_DOLLAR_SIGN; }
\\                    { begin_token(yytext);   return SQL_WON_SIGN; }
.                     { begin_token(yytext);   return yytext[0];    }
%%

void yyerror (const char *s)
{
  printf("Error %s\n",s);
}

int yywrap()
{
  return 1;
}

static int parser_yyinput(char* buff, int max_size)
{
  
  if ( max_size > SQL_this_parser->buffer_size)
  {
    max_size = SQL_this_parser->buffer_size;
  }
  
  if (max_size > 0 )
  {
    memcpy (buff, SQL_this_parser->buffer_current, max_size);
    SQL_this_parser->buffer_current += max_size;
  }
  
  return max_size;
}

static void begin_token (const char * s)
{
};

static void begin_token_name (const char* s)
{
  yylval.cptr = sql_strdup (s);
};

static char input_internal()
{
  char c = input();
  if (c == '\n') 
  {
    SQL_this_parser->line++;
  }
  return c;
}

static char* read_string (char zy, char end)
{
  static char buf[8192];
  char c, *s, *s_end;
  int len;
  
  s = buf;
  s_end = buf + sizeof (buf) + 1;
  len = 0;
  
  do 
  {
    c = input_internal();

    if (c == EOF || c == end || c == '\n' )
    {
      break;
    }
    
    if (c == zy)
    {
      c = input_internal();
      
      if (c == EOF || c == '\n')
      {
        break;
      }
      
      switch (c)
      {
        case 'n': c = '\n'; break;
        case 'b': c = '\b'; break;
        case 't': c = '\t'; break;
        case 'r': c = '\r'; break;
      };
    };
    
    if (s < s_end)
    {
      *(s++) = c;
      len++;
    };
  }
  while (1);
  
  *s = 0;
  
  return sql_strdup (buf);
};

static char* read_c_style_comment (char * s, int size)
{
  char c,last;
  char *s_end, *s_ret = s;
  
  last = 0;
  s_end = s + size - 1;
  
  do 
  {
    c = input_internal();
    
    if ( c == EOF || (c == '/' && last == '*') )
    {
      *s = 0;
      return s_ret;
    }
    
    last = c;
    
    if ( s < s_end)
    {
      *(s++) = c;
    };
    
  } while(1);
  
  return s_ret;
};

static char* read_cpp_style_comment (char * s, int size)
{
  char c;
  char * s_end, *s_ret = s;
  s_end = s + size -1;
  
  do 
  {
    c = input_internal();
    
    if (c == EOF || c == '\n')
    {
      *s = 0;
      return s_ret;
    };
    
    if ( s < s_end)
    {
      *(s++) = c;
    }
  } while(1);
  
  return NULL;
};

static char * read_sql_style_comment (char* s,int size)
{
  return read_cpp_style_comment (s, size);
}

static char* parser_quoted_string(char end)
{
  return NULL;
}

